import React, { Component, useEffect, useState } from 'react';

/**
 * React 生命周期详解
 *
 * 生命周期是指组件从创建到销毁的整个过程，分为三个阶段：
 * 1. 挂载阶段 (Mounting)
 * 2. 更新阶段 (Updating)
 * 3. 卸载阶段 (Unmounting)
 */

// ==================== 类组件生命周期示例 ====================

interface LifecycleDemoState {
  count: number;
  message: string;
}

interface LifecycleDemoProps {
  initialCount?: number;
}

/**
 * 类组件生命周期演示
 * 包含完整的生命周期方法实现
 */
class LifecycleDemo extends Component<LifecycleDemoProps, LifecycleDemoState> {
  timerId?: number;

  /**
   * 1. 构造函数 - 挂载阶段
   * - 在组件实例化时调用
   * - 用于初始化状态和绑定方法
   * - 不要在这里调用 setState
   */
  constructor(props: LifecycleDemoProps) {
    super(props);
    console.log('1. constructor - 构造函数被调用');

    this.state = {
      count: props.initialCount || 0,
      message: '组件已创建',
    };

    // 绑定方法
    this.handleIncrement = this.handleIncrement.bind(this);
  }

  /**
   * 2. componentDidMount - 挂载阶段
   * - 组件挂载到 DOM 后立即调用
   * - 适合进行数据获取、订阅、定时器等操作
   * - 可以安全地调用 setState
   */
  componentDidMount() {
    console.log('3. componentDidMount - 组件已挂载');

    // 模拟数据获取
    setTimeout(() => {
      this.setState({ message: '数据加载完成' });
    }, 1000);

    // 设置定时器
    this.timerId = window.setInterval(() => {
      console.log('定时器执行中...');
    }, 5000);
  }

  /**
   * 3. shouldComponentUpdate - 更新阶段
   * - 在组件更新前调用
   * - 通过返回 true/false 来控制是否重新渲染
   * - 用于性能优化
   */
  shouldComponentUpdate(
    nextProps: LifecycleDemoProps,
    nextState: LifecycleDemoState
  ) {
    console.log('4. shouldComponentUpdate - 检查是否需要更新');

    // 只有当 count 发生变化时才重新渲染
    if (nextState.count !== this.state.count) {
      console.log('count 发生变化，允许更新');
      return true;
    }

    console.log('count 未变化，跳过更新');
    return false;
  }

  /**
   * 4. componentDidUpdate - 更新阶段
   * - 组件更新后立即调用
   * - 适合进行 DOM 操作或根据状态变化执行操作
   * - 可以调用 setState，但必须有条件判断避免无限循环
   */
  componentDidUpdate(
    prevProps: LifecycleDemoProps,
    prevState: LifecycleDemoState
  ) {
    console.log('5. componentDidUpdate - 组件已更新');

    // 检查 count 是否发生变化
    if (prevState.count !== this.state.count) {
      console.log(`count 从 ${prevState.count} 变为 ${this.state.count}`);

      // 根据 count 更新 message
      if (this.state.count > 5) {
        this.setState({ message: '计数已超过 5' });
      }
    }
  }

  /**
   * 5. componentWillUnmount - 卸载阶段
   * - 组件卸载前调用
   * - 用于清理操作：取消订阅、清除定时器、取消网络请求等
   */
  componentWillUnmount() {
    console.log('6. componentWillUnmount - 组件即将卸载');

    // 清除定时器
    if (this.timerId) {
      clearInterval(this.timerId);
      console.log('定时器已清除');
    }
  }

  /**
   * 渲染方法 - 在挂载和更新阶段都会调用
   */
  render() {
    console.log('2. render - 渲染方法被调用');

    return (
      <div
        style={{ padding: '20px', border: '1px solid #ccc', margin: '10px' }}
      >
        <h3>类组件生命周期演示</h3>
        <p>计数: {this.state.count}</p>
        <p>状态: {this.state.message}</p>
        <button onClick={this.handleIncrement}>增加计数</button>
        <button onClick={this.handleReset}>重置计数</button>
      </div>
    );
  }

  handleIncrement() {
    this.setState(prevState => ({
      count: prevState.count + 1,
    }));
  }

  handleReset = () => {
    this.setState({
      count: 0,
      message: '计数已重置',
    });
  };
}

// ==================== 函数组件生命周期示例 ====================

/**
 * 函数组件生命周期演示
 * 使用 React Hooks 模拟生命周期
 */
const FunctionLifecycleDemo: React.FC = () => {
  const [count, setCount] = useState(0);
  const [message, setMessage] = useState('组件已创建');

  /**
   * useEffect 模拟 componentDidMount 和 componentWillUnmount
   * 空依赖数组 [] 表示只在挂载和卸载时执行
   */
  useEffect(() => {
    console.log('函数组件: componentDidMount - 组件已挂载');

    // 模拟数据获取
    setTimeout(() => {
      setMessage('数据加载完成');
    }, 1000);

    const timerId = setInterval(() => {
      console.log('函数组件定时器执行中...');
    }, 5000);

    // 清理函数 - 模拟 componentWillUnmount
    return () => {
      console.log('函数组件: componentWillUnmount - 组件即将卸载');
      clearInterval(timerId);
      console.log('函数组件定时器已清除');
    };
  }, []); // 空依赖数组

  /**
   * useEffect 模拟 componentDidUpdate
   * 监听 count 的变化
   */
  useEffect(() => {
    console.log('函数组件: componentDidUpdate - count 已更新:', count);

    if (count > 5) {
      setMessage('计数已超过 5');
    }
  }, [count]); // 依赖 count

  /**
   * useEffect 模拟 componentDidMount 和 componentDidUpdate
   * 没有依赖数组表示每次渲染后都执行
   */
  useEffect(() => {
    console.log('函数组件: 每次渲染后执行');
  });

  const handleIncrement = () => {
    setCount(prevCount => prevCount + 1);
  };

  const handleReset = () => {
    setCount(0);
    setMessage('计数已重置');
  };

  console.log('函数组件: render - 渲染方法被调用');

  return (
    <div style={{ padding: '20px', border: '1px solid #ccc', margin: '10px' }}>
      <h3>函数组件生命周期演示 (使用 Hooks)</h3>
      <p>计数: {count}</p>
      <p>状态: {message}</p>
      <button onClick={handleIncrement}>增加计数</button>
      <button onClick={handleReset}>重置计数</button>
    </div>
  );
};

// ==================== 生命周期阶段总结 ====================

/**
 * 生命周期阶段总结组件
 */
const LifecycleSummary: React.FC = () => {
  return (
    <div
      style={{
        padding: '20px',
        border: '1px solid #ddd',
        margin: '10px',
        backgroundColor: '#f5f5f5',
      }}
    >
      <h3>React 生命周期阶段总结</h3>

      <div style={{ marginBottom: '15px' }}>
        <h4>📌 挂载阶段 (Mounting)</h4>
        <ul>
          <li>
            <strong>constructor</strong> - 构造函数，初始化状态和方法绑定
          </li>
          <li>
            <strong>render</strong> - 渲染组件
          </li>
          <li>
            <strong>componentDidMount</strong> - 组件挂载后，适合数据获取和订阅
          </li>
        </ul>
      </div>

      <div style={{ marginBottom: '15px' }}>
        <h4>🔄 更新阶段 (Updating)</h4>
        <ul>
          <li>
            <strong>shouldComponentUpdate</strong> -
            决定是否重新渲染，用于性能优化
          </li>
          <li>
            <strong>render</strong> - 重新渲染组件
          </li>
          <li>
            <strong>componentDidUpdate</strong> - 组件更新后，适合 DOM 操作
          </li>
        </ul>
      </div>

      <div style={{ marginBottom: '15px' }}>
        <h4>🗑️ 卸载阶段 (Unmounting)</h4>
        <ul>
          <li>
            <strong>componentWillUnmount</strong> -
            组件卸载前，清理定时器、取消订阅等
          </li>
        </ul>
      </div>

      <div style={{ marginBottom: '15px' }}>
        <h4>🎣 函数组件 Hooks 对应关系</h4>
        <ul>
          <li>
            <strong>useEffect(空依赖数组)</strong> - 模拟 componentDidMount +
            componentWillUnmount
          </li>
          <li>
            <strong>useEffect(有依赖数组)</strong> - 模拟 componentDidUpdate
          </li>
          <li>
            <strong>useEffect(无依赖数组)</strong> - 每次渲染后执行
          </li>
        </ul>
      </div>
    </div>
  );
};

// ==================== 主组件 ====================

/**
 * 生命周期演示主组件
 */
const LifecycleApp: React.FC = () => {
  const [showClassComponent, setShowClassComponent] = useState(true);
  const [showFunctionComponent, setShowFunctionComponent] = useState(true);

  return (
    <div style={{ padding: '20px' }}>
      <h1>React 生命周期完整演示</h1>

      <div style={{ marginBottom: '20px' }}>
        <button onClick={() => setShowClassComponent(!showClassComponent)}>
          {showClassComponent ? '隐藏' : '显示'} 类组件
        </button>
        <button
          onClick={() => setShowFunctionComponent(!showFunctionComponent)}
          style={{ marginLeft: '10px' }}
        >
          {showFunctionComponent ? '隐藏' : '显示'} 函数组件
        </button>
      </div>

      {showClassComponent && <LifecycleDemo initialCount={0} />}
      {showFunctionComponent && <FunctionLifecycleDemo />}

      <LifecycleSummary />
    </div>
  );
};

export default LifecycleApp;
export { LifecycleDemo, FunctionLifecycleDemo, LifecycleSummary };
